<?php
	/*
	 * Copyright 2009 Douglas Lockamy, dlockamy_at_gmail.com
	 * All rights reserved. Distributed under the terms of the MIT License.
	 */	
	<?php
		/*
		 * Copyright 2009 Douglas Lockamy, dlockamy_at_gmail.com
		 * All rights reserved. Distributed under the terms of the MIT License.
		 */
		/*
		 vfs spec
		 
		 FS File Types:
		 1 Directory
		 2 Text File
		 3 Binary File
		 4 Symlink
		 5 Mount Point
		 
		 FS File Read Flags
		 1 Request Type
		 2 Return Array of File in Directory
		 3 Read text/data file
		 
		 */
		
		$MAX_FILE_DEPTH = 100;
		
		function jsInclude(jsFile)
		{
			document.write('script type=\"\" src"'+jsFile + '\"></scr' + 'ipt>');
		};
		
		var vfsList = new Array();
		
		function vfsNode() {
			vfsNode.Name = "";
			vfsNode.item = 0;
			vfsNode.Parent = 0;
		};
		
		message_vfsNode = vfsList[vfsList.length]=new vfsNode();
		message_vfsNode.Name = 'messagefs';
		
		proc_vfsNode = vfsList[vfsList.length]=new vfsNode();
		proc_vfsNode.Name = 'procfs';
		
		
		fsList = new Array();
		var rootfs;
		
		if (!this.vfs) vfs = {};
		
		vfs.version = '0.1';
		
		vfs.init = function()
		{
			
			rootfs = new fileNode();
			rootfs.Name="/";
			rootfs.Type = 1;
			rootfs.prev = 0;
			rootfs.next = 0;
			rootfs.Data = new Array();
			rootfs.Parent = 0;
			
			rootfs.Data = new Array();
			rootfs.Data[0] = new fileNode();
			
			var etc = rootfs.Data[0];
			etc.Name="etc";
			etc.Type = 1;
			etc.Data=new Array();
			etc.prev=0;
			etc.next=0; 
			etc.Parent = rootfs;
			
			var fstab = etc.Data[0] = new fileNode();
			fstab.Name = "fstab"
			fstab.Type = 2;
			fstab.Data = "/ ro Root\n /Volumes phpfs username"; 
			fstab.prev=0; 
			fstab.next=0; 
			fstab.Parent = rootfs;  
			
			vfs.write('/local',1,1);
			vfs.write('/home',1,1);    
			vfs.write('/dev',1,1);    
			vfs.write('/var',1,1);
			
		};
		
		vfs.mount = function(serverAddress,fs_type,mountPoint,user,pass,argv)
		{
			var mPath = benix.fsBuildMountPath(rootfs,mountPoint);
			var name = mountPoint.split("/");
			var aNode = vfs.walk(mPath);
			var counter = 0;
			
			while(vfsList[counter].Name != fs_type && counter < vfsList.length-1)
			{  
				counter++;
			}
			if(aNode.Type == 1 && vfsList[counter].Name == fs_type)
			{
				aNode.Data[aNode.Data.length] = new fileNode(); 
				
				var mounter = aNode.Data[aNode.Data.length - 1 ];
				
				if(aNode.Data.length > 1)
					aNode.Data[aNode.Data.length-2].next = mounter;
				
				var aNumber = aNode.Data.length - 1;
				
				mounter.Name=name[name.length-1];
				mounter.Type = 5;
				mounter.Data= new mountNode();
				mounter.Data[0]=fs_type;
				mounter.Data[1]=serverAddress;
				mounter.Data[2]=0;
				mounter.Data[3]=vfsList[counter].item;
				mounter.Parent = aNode;
				
				if(aNode.Data.length < 1)
					mounter.prev=0;
				else
					mounter.prev=aNode.Data[aNode.Data.length-2];
				
				mounter.next=0;
				
				return(vfsList[counter].item.mount(serverAddress,fs_type,mountPoint,user,pass,argv) );
			}
			else
				return -1;
		};
		
		vfs.umount = function(mountPoint)
		{
			var aNode = vfs.walk(mountPoint);
			if(aNode.Type == 5)
			{
				if(!aNode.Data[3].umount() )
				{
					vfs.write(mountPoint,0,null);
				}
				return 0;
			}
			else  
				benix.stdout('<br>Not a mount point<br>');
		};
		
		vfs.walk = function(fsNode)
		{
			return(benix.fsWalk(rootfs,fsNode) );
		};
		
		vfs.read = function(path,flags,buffer,offset,length,sessionKey)
		{
			if(flags =='1')
			{
				var readNode = vfs.walk(path);
				
				if(readNode.Type == 1)
					return 1;
				if(readNode.Type==5)
				{
					readNode.Data[3].read(path,1);
					return 1;
				}           
				else
					return 0;
			}
			if(flags =='2')
			{    
				var readNode = vfs.walk(path);
				
				if(readNode.Type == 1)
					return readNode;
				if(readNode.Type==5)
				{
					var loadPath = benix.parsePath(aNode,path);
					return(readNode.Data[3].read(loadPath,flags) );
				}           
				else
					return readNode;
			}
			if(flags =='3')
			{  
				var readNode = vfs.walk(path);
				
				if(readNode.Type == 1)
				{
					if(readNode.Data[0].Name)
						return readNode.Data[0].Name;
					else
						return "File Read Error"
						}
				if(readNode.Type==5)
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(readNode.Data[3].read(loadPath,flags,buffer,offset,length,sessionKey) );
				}           
				else
					return readNode.Data;    
			}
			else
				return -1;
		};
		
		vfs.write = function(path,flags,buffer,offset,length,sessionKey)
		{
			/*
			 FS File Read Flags
			 1 Request Type
			 2 Return Array of File in Directory
			 3 Read text/data file*/
			
			var workPath = '/';
			var aNode = 0;
			var pathArray = path.split('/');
			var counter=0;
			
			while(counter <= pathArray.length-2)
			{
				if(workPath == '/')
					workPath = workPath + pathArray[counter];
				else
					workPath = workPath + '/' + pathArray[counter];
				counter++;
			}
			
			if(flags==0)
			{
				//unlink a node
				counter = 0;
				aNode = vfs.walk(path);
				alert(aNode.Name + ' ' + aNode.Type);
				if(aNode.Type == 5)
				{
					var loadPath = benix.parsePath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer,offset,length,sessionKey) );
				};
				
				var prevNode = aNode.prev;   
				var nextNode = aNode.next;      
				
				while(aNode.Parent.Data[counter].Name != aNode.Name && counter < aNode.Parent.Data.length)
				{
					counter++;
				}
				
				aNode.Parent.Data.splice(counter,1);
				
				prevNode.next = nextNode;
				nextNode.prev = prevNode;
			}
			
			if(flags==1)
			{
				aNode = vfs.walk(workPath);
				
				if(aNode.Type == 1 && buffer == 1)
				{
					aNode.Data[aNode.Data.length] = new fileNode;
					var newDir = aNode.Data[aNode.Data.length-1];
					newDir.Name = pathArray[pathArray.length-1];
					newDir.Type = 1;
					newDir.next = 0;
					newDir.Data = new Array();
					newDir.prev = aNode.Data[aNode.Data.length-1];
					newDir.Parent = aNode;
					
					if(aNode.Data.length >= 2 )
					{        
						aNode.Data[aNode.Data.length-2].next=newDir;
					}          
				}
				
				else if(aNode.Type==5 )
				{
					var loadPath = benix.parsePath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer,offset,length,sessionKey) );
				}  
				// alert('write dir: ' + aNode.Name + ',' + workPath);        
				else
					return -1;
				
			}
			else if(flags==2)
			{
				aNode = vfs.walk(workPath);
				
				if(aNode.Type==1 )
				{
					var newfile = aNode.Data[aNode.Data.length] = new fileNode();
					newfile.Name = pathArray[pathArray.length-1];
					newfile.Type = 2;
					newfile.next = 0;
					newfile.Data = buffer;
					newfile.prev = aNode.Data[aNode.Data.length-1];
					
					if(aNode.Data.length >= 2 )
					{        
						aNode.Data[aNode.Data.length-2].next=newfile;
					}           
				}
				
				if(aNode.Type==5 )
				{
					var loadPath = benix.parsePath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer,offset,length,sessionKey) );
				}  
				
				else
					return -1;
			}
			else if(flags==3)
			{
				alert('link unsupported at this time');
			}
			else 
				return -1;
			
		};
		
		vfs.stat = function(path)
		{
			var aNode = vfs.walk(path);
			benix.stdout(aNode.Type + '<br>');
			benix.stdout(aNode.Data.length+ '<br>' );
		};
		
		
		//proc fs
		if (!this.procfs) procfs = {};
		proc_vfsNode.item=procfs;
		procfs.version = '0.1';
		
		procfs.init = function()
		{
			procRoot = new fileNode();
			procRoot.Name="/";
			procRoot.Type = 1;
			procRoot.prev = 0;
			procRoot.next = 0;
			procRoot.Data = new Array();
			procRoot.Parent = 0;
			
			procRoot.Data[0] = new fileNode();
			
			var ctl = procRoot.Data[0];
			ctl.Name="bash";
			ctl.Type=2;
			ctl.prev=0;
			ctl.next=0;
			ctl.Data="a bunch of text";
			
			
			
		};
		
		procfs.mount = function(serverAddress,fs_type,mountPoint,user,pass,argv)
		{
			/*
			 var mPath = benix.fsBuildMountPath(rootfs,mountPoint);
			 var name = mountPoint.split("/");
			 var aNode = vfs.walk(mPath);
			 var counter = 0;
			 
			 while(vfsList[counter].Name != fs_type && counter < vfsList.length-1)
			 {  
			 counter++;
			 }
			 if(aNode.Type == 1 && vfsList[counter].Name == fs_type)
			 {
			 aNode.Data[aNode.Data.length] =  new fileNode(); 
			 
			 var mounter = aNode.Data[aNode.Data.length - 1 ];
			 
			 aNode.Data[aNode.Data.length-1].Next = mounter;
			 
			 mounter.Name=name[name.length-1];
			 mounter.Type = 5;
			 mounter.Data= new mountNode();
			 mounter.Data[0]=fs_type;
			 mounter.Data[1]=serverAddress;
			 mounter.Data[2]=0;
			 mounter.Data[3]=vfsList[counter].item;
			 mounter.Parent = aNode;
			 
			 if(aNode.Data.length < 1)
			 mounter.prev=0;
			 else
			 mounter.prev=aNode.Data[aNode.Data.length-2];
			 mounter.next=0;
			 
			 vfsList[counter].item.init();
			 
			 return 0;
			 }
			 else*/
			return -1;
		};
		
		procfs.umount = function(mountPoint)
		{
			var aNode = vfs.walk(mountPoint);
			if(aNode.Type == 5)
			{
				if(!aNode.Data[3].umount() )
				{
					vfs.write(mountPoint,0,null);
				}
				return 0;
			}
			else  
				benix.stdout('<br>Not a mount point<br>');
		};
		
		procfs.read = function(path,flags,buffer,offset,length,sessionKey)
		{
			//alert('procfs.read()' + ' ' + flags + path);
			if(flags =='1')
			{
				var readNode = benix.fsWalk(procRoot,path);
				
				if(readNode.Type == 1)
					return 1;
				if(readNode.Type==5)
				{
					readNode.Data[3].read(path,1);
					return 1;
				}           
				else
					return 0;
			}
			if(flags =='2')
			{    
				var readNode = benix.fsWalk(procRoot,path);
				
				if(readNode.Type == 1)
					return readNode;
				if(readNode.Type==5)
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(readNode.Data[3].read(loadPath,flags) );
				}           
				else
					return readNode;
			}
			if(flags =='3')
			{  
				var readNode = benix.walk(procRoot,path);
				
				if(readNode.Type == 1)
				{
					if(readNode.Data[0].Name)
						return readNode.Data[0].Name;
					else
						return "File Read Error"
						}
				if(readNode.Type==5)
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(readNode.Data[3].read(loadPath,flags) );
				}           
				else
					return readNode.Data;    
			}
			else
				return -1;
		};
		
		procfs.write = function(path,flags,buffer,offset,length,sessionKey)
		{
			
			var workPath = '/';
			var aNode = 0;
			var pathArray = path.split('/');
			var counter=0;
			
			while(counter <= pathArray.length-2)
			{
				if(workPath == '/')
					workPath = workPath + pathArray[counter];
				else
					workPath = workPath + '/' + pathArray[counter];
				counter++;
			}
			
			if(flags==0)
			{
				//unlink a node
				counter = 0;
				aNode = benix.fsWalk(procRoot,path);
				
				if(aNode.Type == 5)
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer) );
				};
				
				var prevNode = aNode.prev;   
				var nextNode = aNode.next;      
				
				while(aNode.Parent.Data[counter].Name != aNode.Name && counter < aNode.Parent.Data.length)
				{
					counter++;
				}
				
				aNode.Parent.Data.splice(counter,1);
				
				prevNode.next = nextNode;
				nextNode.prev = prevNode;
			}
			
			if(flags==1)
			{
				aNode = benix.fsWalk(procRoot,workPath);
				
				if(aNode.Type == 1 && buffer == 1)
				{
					aNode.Data[aNode.Data.length] = new fileNode;
					var newDir = aNode.Data[aNode.Data.length-1];
					newDir.Name = pathArray[pathArray.length-1];
					newDir.Type = 1;
					newDir.next = 0;
					newDir.Data = new Array();
					newDir.prev = aNode.Data[aNode.Data.length-1];
					newDir.Parent = aNode;
					
					if(aNode.Data.length >= 2 )
					{        
						aNode.Data[aNode.Data.length-2].next=newDir;
					}          
				}
				
				if(aNode.Type==5 )
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer) );
				}  
				
				else
					return -1;
			}
			else if(flags==2)
			{
				aNode = benix.walk(procRoot,workPath);
				
				if(aNode.Type==1 )
				{
					var newfile = aNode.Data[aNode.Data.length] = new fileNode();
					newfile.Name = pathArray[pathArray.length-1];
					newfile.Type = 2;
					newfile.next = 0;
					newfile.Data = buffer;
					newfile.prev = aNode.Data[aNode.Data.length-1];
					
					if(aNode.Data.length >= 2 )
					{        
						aNode.Data[aNode.Data.length-2].next=newfile;
					}           
				}
				
				if(aNode.Type==5 )
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer) );
				}  
				
				else
					return -1;
			}
			else if(flags==3)
			{
				alert('link unsupported at this time');
			}
			else 
				return -1;
			
		};
		
		//message fs
		
		if (!this.messagefs) messagefs = {};
		message_vfsNode.item=messagefs;
		messagefs.version = '0.1';
		
		messagefs.init = function()
		{
			
			messageRoot = new fileNode();
			messageRoot.Name="/";
			messageRoot.Type = 1;
			messageRoot.prev = 0;
			messageRoot.next = 0;
			messageRoot.Data = new Array();
			messageRoot.Parent = 0;
		};
		
		messagefs.mount = function(serverAddress,fs_type,mountPoint,user,pass,argv)
		{
			/*
			 var mPath = benix.fsBuildMountPath(rootfs,mountPoint);
			 var name = mountPoint.split("/");
			 var aNode = benix.fsWalk(messageRoot,mPath);
			 var counter = 0;
			 
			 while(vfsList[counter].Name != fs_type && counter < vfsList.length-1)
			 {  
			 counter++;
			 }
			 if(aNode.Type == 1 && vfsList[counter].Name == fs_type)
			 {
			 aNode.Data[aNode.Data.length] =  new fileNode(); 
			 
			 var mounter = aNode.Data[aNode.Data.length - 1 ];
			 
			 aNode.Data[aNode.Data.length-1].Next = mounter;
			 
			 mounter.Name=name[name.length-1];
			 mounter.Type = 5;
			 mounter.Data= new mountNode();
			 mounter.Data[0]=fs_type;
			 mounter.Data[1]=serverAddress;
			 mounter.Data[2]=0;
			 mounter.Data[3]=vfsList[counter].item;
			 mounter.Parent = aNode;
			 
			 if(aNode.Data.length < 1)
			 mounter.prev=0;
			 else
			 mounter.prev=aNode.Data[aNode.Data.length-2];
			 mounter.next=0;
			 
			 vfsList[counter].item.init();
			 
			 return 0;
			 }
			 else*/
			return -1;
		};
		
		messagefs.umount = function(mountPoint)
		{
			var aNode = benix.fsWalk(messageRoot,mountPoint);
			if(aNode.Type == 5)
			{
				if(!aNode.Data[3].umount() )
				{
					vfs.write(mountPoint,0,null);
				}
				return 0;
			}
			else  
				benix.stdout('<br>Not a mount point<br>');
		};
		
		vfs.dumpNode = function(aNode)
		{
			var x = 0;
			xNode = vfs.walk(aNode );
			while(x < xNode.Data.length)
			{
				benix.stdout("node:" + xNode.Data[x].Name + "<br>");
				x++;
			};
		};
		
		var readcount = 0;
		
		messagefs.read = function(path,flags,buffer,offset,length,sessionKey)
		{
			
			readcount = readcount++;
			
			if(flags =='1')
			{
				var readNode = benix.fsWalk(messageRoot,path);
				
				if(readNode)
				{
					if(readNode.Type == 1)
						return 1;
					if(readNode.Type==5)
					{
						readNode.Data[3].read(path,1);
						return 1;
					}           
					else
						return 0;
				}
				
				return 0;
			}
			if(flags =='2')
			{    
				var readNode = benix.fsWalk(messageRoot,path);
				
				if(readNode.Type == 1)
					return readNode;
				if(readNode.Type==5)
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(readNode.Data[3].read(loadPath,flags) );
				}           
				else
					return readNode;
			}
			if(flags =='3')
			{  
				var readNode = benix.fsWalk(messageRoot,path);
				
				if(readNode.Type == 1)
				{
					if(readNode.Data[0].Name)
						return readNode.Data[0].Name;
					else
						return "File Read Error"
						}
				if(readNode.Type==5)
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(readNode.Data[3].read(loadPath,flags) );
				}           
				else
					return readNode.Data;    
			}
			else
				return -1;
		};
		
		messagefs.write = function(path,flags,buffer,offset,length,sessionKey)
		{
			var workPath = '/';
			var aNode = 0;
			var pathArray = path.split('/');
			var counter=0;
			
			while(counter <= pathArray.length-2)
			{
				if(workPath == '/')
					workPath = workPath + pathArray[counter];
				else
					workPath = workPath + '/' + pathArray[counter];
				counter++;
			}
			
			if(flags==0)
			{
				//unlink a node
				counter = 0;
				aNode = benix.fsWalk(messageRoot,path);
				
				if(aNode.Type == 5)
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer) );
				};
				
				var prevNode = aNode.prev;   
				var nextNode = aNode.next;      
				
				while(aNode.Parent.Data[counter].Name != aNode.Name && counter < aNode.Parent.Data.length)
				{
					counter++;
				}
				
				aNode.Parent.Data.splice(counter,1);
				
				prevNode.next = nextNode;
				nextNode.prev = prevNode;
			}
			
			if(flags==1)
			{
				aNode = benix.fsWalk(messageRoot,workPath);
				
				if(aNode.Type == 1 && buffer == 1)
				{
					aNode.Data[aNode.Data.length] = new fileNode;
					var newDir = aNode.Data[aNode.Data.length-1];
					newDir.Name = pathArray[pathArray.length-1];
					newDir.Type = 1;
					newDir.next = 0;
					newDir.Data = new Array();
					newDir.prev = aNode.Data[aNode.Data.length-1];
					newDir.Parent = aNode;
					
					if(aNode.Data.length >= 2 )
					{        
						aNode.Data[aNode.Data.length-2].next=newDir;
					}          
				}
				
				if(aNode.Type==5 )
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer) );
				}  
				
				else
					return -1;
			}
			else if(flags==2)
			{
				aNode = benix.fsWalk(messageRoot,workPath);
				
				if(aNode.Type==1 )
				{
					var newfile = aNode.Data[aNode.Data.length] = new fileNode();
					newfile.Name = pathArray[pathArray.length-1];
					newfile.Type = 2;
					newfile.next = 0;
					newfile.Data = buffer;
					newfile.prev = aNode.Data[aNode.Data.length-1];
					
					if(aNode.Data.length >= 2 )
					{        
						aNode.Data[aNode.Data.length-2].next=newfile;
					}           
				}
				
				if(aNode.Type==5 )
				{
					var loadPath = benix.fsBuildMountPath(aNode,path);
					
					return(aNode.Data[3].write(loadPath,flags,buffer) );
				}  
				
				else
					return -1;
			}
			else if(flags==3)
			{
				alert('link unsupported at this time');
			}
			else 
				return -1;
			
		};
		
		
		
		
	?>
?>







